package com.example.utils;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.example.ormlite.DBHelper_DataDir;
import com.j256.ormlite.dao.BaseDaoImpl;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
import com.j256.ormlite.db.DatabaseType;
import com.j256.ormlite.field.FieldType;
import com.j256.ormlite.logger.Logger;
import com.j256.ormlite.logger.LoggerFactory;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableInfo;

public class ORMLiteTableUtils {
	private static Logger logger = LoggerFactory.getLogger(ORMLiteTableUtils.class);

	public static <T, ID> String alterTableColumnAndColumnType_SQL(ConnectionSource connectionSource, Class<T> dataClass)
			throws SQLException {
		Dao<T, ID> dao = DaoManager.createDao(connectionSource, dataClass);
		return doAlterTable(connectionSource, ((BaseDaoImpl<?, ?>) dao).getTableInfo());
	}
	
	
	
	private static <T, ID> String doAlterTable(ConnectionSource connectionSource, TableInfo<T, ID> tableInfo) throws SQLException {
		DatabaseType databaseType = connectionSource.getDatabaseType();
		logger.info("alter table '{}'", tableInfo.getTableName());
		List<String> statements = new ArrayList<String>();
		List<String> queriesAfter = new ArrayList<String>();
		String sql_alterTable = getAlterTableStatements(databaseType, tableInfo, statements, queriesAfter);
		return sql_alterTable;
		
	}
	
	/**
	 * Generate and return the list of statements to create a database table and any associated features.
	 * @return 
	 */
	private static <T, ID> String getAlterTableStatements(DatabaseType databaseType, TableInfo<T, ID> tableInfo,
			List<String> statements, List<String> queriesAfter) throws SQLException {
		StringBuilder sb = new StringBuilder(256);
		List<String> additionalArgs = new ArrayList<String>();
		List<String> statementsBefore = new ArrayList<String>();
		List<String> statementsAfter = new ArrayList<String>();
		// our statement will be set here later
		boolean first = true;
		for (FieldType fieldType : tableInfo.getFieldTypes()) {
			// skip foreign collections
			if (fieldType.isForeignCollection()) {
				continue;
			} else if (first) {
				first = false;
			} else {
				sb.append(", ");
			}
			String columnDefinition = fieldType.getColumnDefinition();
			if (columnDefinition == null) {
				// we have to call back to the database type for the specific create syntax
				databaseType.appendColumnArg(tableInfo.getTableName(), sb, fieldType, additionalArgs, statementsBefore,
						statementsAfter, queriesAfter);
			} else {
				// hand defined field
				databaseType.appendEscapedEntityName(sb, fieldType.getColumnName());
				sb.append(' ').append(columnDefinition).append(' ');
			}
		}
		// add any sql that sets any primary key fields
		databaseType.addPrimaryKeySql(tableInfo.getFieldTypes(), additionalArgs, statementsBefore, statementsAfter,
				queriesAfter);
		// add any sql that sets any unique fields
		databaseType.addUniqueComboSql(tableInfo.getFieldTypes(), additionalArgs, statementsBefore, statementsAfter,
				queriesAfter);
		for (String arg : additionalArgs) {
			// we will have spat out one argument already so we don't have to do the first dance
			sb.append(", ").append(arg);
		}
		return sb.substring(0, sb.length()-1).toString();
	}
	
	public static <T, ID> String alterTableColumnAndColumnTypeByFieldTypes_SQL(ConnectionSource connectionSource, Class<T> dataClass, FieldType[] fieldTypes)
			throws SQLException {
		Dao<T, ID> dao = DaoManager.createDao(connectionSource, dataClass);
		return doAlterTableByFieldTypes_SQL(connectionSource, ((BaseDaoImpl<?, ?>) dao).getTableInfo(),fieldTypes);
	}
	
	
	
	private static <T, ID> String doAlterTableByFieldTypes_SQL(ConnectionSource connectionSource, TableInfo<T, ID> tableInfo, FieldType[] fieldTypes) throws SQLException {
		DatabaseType databaseType = connectionSource.getDatabaseType();
		logger.info("alter table '{}'", tableInfo.getTableName());
		List<String> statements = new ArrayList<String>();
		List<String> queriesAfter = new ArrayList<String>();
		String sql_alterTable = getAlterTableStatementsByFieldTypes(databaseType, tableInfo, statements, queriesAfter,fieldTypes);
		return sql_alterTable;
		
	}
	
	/**
	 * Generate and return the list of statements to create a database table and any associated features.
	 * @return 
	 */
	private static <T, ID> String getAlterTableStatementsByFieldTypes(DatabaseType databaseType, TableInfo<T, ID> tableInfo,
			List<String> statements, List<String> queriesAfter,FieldType[] fieldTypes) throws SQLException {
		StringBuilder sb = new StringBuilder(256);
		List<String> additionalArgs = new ArrayList<String>();
		List<String> statementsBefore = new ArrayList<String>();
		List<String> statementsAfter = new ArrayList<String>();
		// our statement will be set here later
		boolean first = true;
		for (FieldType fieldType : fieldTypes) {
			// skip foreign collections
			if (fieldType.isForeignCollection()) {
				continue;
			} else if (first) {
				first = false;
			} else {
				sb.append(", ");
			}
			String columnDefinition = fieldType.getColumnDefinition();
			if (columnDefinition == null) {
				// we have to call back to the database type for the specific create syntax
				databaseType.appendColumnArg(tableInfo.getTableName(), sb, fieldType, additionalArgs, statementsBefore,
						statementsAfter, queriesAfter);
			} else {
				// hand defined field
				databaseType.appendEscapedEntityName(sb, fieldType.getColumnName());
				sb.append(' ').append(columnDefinition).append(' ');
			}
		}
		// add any sql that sets any primary key fields
		databaseType.addPrimaryKeySql(tableInfo.getFieldTypes(), additionalArgs, statementsBefore, statementsAfter,
				queriesAfter);
		// add any sql that sets any unique fields
		databaseType.addUniqueComboSql(tableInfo.getFieldTypes(), additionalArgs, statementsBefore, statementsAfter,
				queriesAfter);
		for (String arg : additionalArgs) {
			// we will have spat out one argument already so we don't have to do the first dance
			sb.append(", ").append(arg);
		}
		System.out.println("sb.toString():"+sb.toString());
		return sb.substring(0, sb.length()-1).toString();
	}
	
	
}
